package org.rslai.tcedit.web;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.hibernate.validator.InvalidStateException;
import org.hibernate.validator.InvalidValue;
import org.rslai.tcedit.domain.Catalog;
import org.rslai.tcedit.domain.TestCase;
import org.rslai.tcedit.domain.User;
import org.rslai.tcedit.domain.Version;
import org.rslai.tcedit.exception.ApplicationException;
import org.rslai.tcedit.security.SecurityUtil;
import org.rslai.tcedit.util.HttpUtil;
import org.rslai.tcedit.util.SessionUtil;
import org.rslai.tcedit.web.core.AbstractMvcController;

/**
 * 树，包括查询子目录显示信息、增、删、改等
 * 
 * @author rslai
 * 
 * @spring.bean name="/tree.jspx"
 */
public class TreeController extends AbstractMvcController {

	@Override
	public Map<String, Object> getModel(HttpServletRequest request, HttpServletResponse response) throws Exception {
		response.setContentType("application/json; charset=utf-8");

		Map<String, Object> map = new HashMap<String, Object>();
		Map<String, Object> mapJson = new HashMap<String, Object>();
		List<Catalog> catalogList = null;
		List<TestCase> testCaseList = null;

		String action = HttpUtil.getString(request, "action", "").toLowerCase();
		String rel = HttpUtil.getString(request, "rel", "").toLowerCase();
		String id = HttpUtil.getString(request, "id", "").toLowerCase();
		String onlyCatalog = HttpUtil.getString(request, "onlyCatalog", "").toLowerCase();

		// ID 为空时为查找跟目录
		if (id.equals("")) {
			id = org.rslai.tcedit.domain.Catalog.ROOT_ID;
		}

		try {

			if (action.equals("get_children")) { // 查询子目录
				if (SessionUtil.getCurrentVersionID(request).equals("")) {
					throw new ApplicationException("请选择一个产品及其版本 ！");
				}
				catalogList = catalogService.queryCatalog(SessionUtil.getCurrentProductID(request), SessionUtil.getCurrentVersionID(request), id, true);
				if (onlyCatalog.equals("true")) {
					testCaseList = new ArrayList<TestCase>();
				} else {
					testCaseList = testCaseService.queryTestCase(SessionUtil.getCurrentProductID(request), id, true);
				}
				map.put("returnData", toJsonStr(catalogList, testCaseList, SessionUtil.getCurrentProductID(request)));
			} else if (action.equals("remove_node")) { // 删除
				if (rel.equals("folder")) { // 删除一个分类
					Catalog catalog = (Catalog) catalogService.query(SessionUtil.getCurrentProductID(request), Catalog.class, id);
					catalogService.delete(SessionUtil.getCurrentProductID(request), catalog);
					mapJson.put("status", 1);
				} else { // 删除一个用例
					TestCase testCase = (TestCase) testCaseService.query(SessionUtil.getCurrentProductID(request), TestCase.class, id);
					testCaseService.delete(testCase);
					mapJson.put("status", 1);
				}
				map.put("returnData", toJsonStr(mapJson));
			} else if (action.equals("move_node")) { // 移动
				String pid = HttpUtil.getString(request, "pid", "");
				if (pid.equals("")) {
					pid = Catalog.ROOT_ID;
				}
				if (rel.equals("folder")) { // 移动-分类
					Catalog catalog = (Catalog) catalogService.query(SessionUtil.getCurrentProductID(request), Catalog.class, id);
					if (HttpUtil.getString(request, "copy", "").equals("1")) { // 移动-分类-复制
						Catalog newCatalog = new Catalog();
						newCatalog.setVersion(catalog.getVersion());
						newCatalog.setParentCatalogID(pid);
						newCatalog.setName(catalog.getName());
						newCatalog.setDescribing(catalog.getDescribing());
						catalogService.create(SessionUtil.getCurrentProductID(request), newCatalog);
						mapJson.put("id", newCatalog.getId());
					} else { // 移动-分类-移动
						if (!catalog.getParentCatalogID().equals(pid)) {
							catalog.setParentCatalogID(pid);
							catalogService.update(catalog);
						}
						mapJson.put("id", 1);
					}
				} else { // 移动-用例
					TestCase testCase = (TestCase) testCaseService.query(SessionUtil.getCurrentProductID(request), TestCase.class, id);
					if (HttpUtil.getString(request, "copy", "").equals("1")) { // 移动-用例-复制
						TestCase newTestCase = new TestCase();
						newTestCase.setVersion(testCase.getVersion());
						newTestCase.setCatalogID(pid);
						newTestCase.setDescribing(testCase.getDescribing());
						newTestCase.setPremiss(testCase.getPremiss());
						newTestCase.setCaseState(testCase.getCaseState());
						newTestCase.setRemark(testCase.getRemark());
						newTestCase.setSteps(testCase.getSteps());
						newTestCase.setExResult(testCase.getExResult());
						newTestCase.setUser((User) userService.query(SecurityUtil.getCurrentUsername()));
						newTestCase.setEditDate(new Date());
						testCaseService.create(SessionUtil.getCurrentProductID(request), newTestCase);
						mapJson.put("id", newTestCase.getId());
					} else { // 移动-用例-移动
						if (!testCase.getCatalogID().equals(pid)) {
							testCase.setCatalogID(pid);
							testCaseService.update(testCase);
						}
						mapJson.put("id", 1);
					}
					
				}
				mapJson.put("status", 1);
				map.put("returnData", toJsonStr(mapJson));
			} else if (action.equals("rename_node")) { // 编辑
				String newText = HttpUtil.getString(request, "newText", "");
				if (rel.equals("folder")) { // 编辑-分类
					Catalog catalog = (Catalog) catalogService.query(SessionUtil.getCurrentProductID(request), Catalog.class, id);
					if (catalog.getName()!=newText) {
						catalog.setName(newText);
						catalogService.update(catalog);
					}
					mapJson.put("status", 1);
				} else { // 编辑-用例
					TestCase testCase = (TestCase) testCaseService.query(SessionUtil.getCurrentProductID(request), TestCase.class, id);
					if (testCase.getDescribing()!=newText) {
						testCase.setDescribing(newText);
						testCaseService.update(testCase);
					}
					mapJson.put("status", 1);
				}
				map.put("returnData", toJsonStr(mapJson));
			} else if (action.equals("create_node")) { // 新增
				String pid = HttpUtil.getString(request, "pid", "");
				if (pid.equals("")) {
					pid = Catalog.ROOT_ID;
				}
				String newText = HttpUtil.getString(request, "newText", "");
				if (rel.equals("folder")) { // 新增-分类
					Catalog catalog = new Catalog();
					catalog.setVersion((Version) versionService.query(Version.class, SessionUtil.getCurrentVersionID(request)));
					catalog.setParentCatalogID(pid);
					catalog.setName(newText);
					catalogService.create(SessionUtil.getCurrentProductID(request), catalog);
					mapJson.put("status", 1);
					mapJson.put("id", catalog.getId());
				} else {// 新增-用例
					TestCase testCase = new TestCase();
					testCase.setVersion((Version) versionService.query(Version.class, SessionUtil.getCurrentVersionID(request)));
					testCase.setCatalogID(pid);
					testCase.setDescribing(newText);
					testCase.setUser((User) userService.query(SecurityUtil.getCurrentUsername()));
					testCase.setEditDate(new Date());
					testCaseService.create(SessionUtil.getCurrentProductID(request), testCase);
					mapJson.put("status", 1);
					mapJson.put("id", testCase.getId());
				}
				map.put("returnData", toJsonStr(mapJson));
			}

		} catch(Exception e) {
			mapJson.clear();
			mapJson.put("status", 0);
			mapJson.put("error", convertException(e));
			map.put("returnData", toJsonStr(mapJson));
		}

		return map;
	}

	@Override
	public String getView(HttpServletRequest request, HttpServletResponse response) {
		return "/tree.htm";
	}

	private String convertException(Exception e) {
		if (e instanceof ApplicationException) {
			return e.getMessage();
		} else if (e instanceof InvalidStateException) {
			StringBuffer sb = new StringBuffer(128);
			InvalidValue[] ivs = ((InvalidStateException) e).getInvalidValues();
			for (InvalidValue iv : ivs)
				sb.append(iv.getMessage()).append("<br/>");
			return sb.toString();
		}
		return e.getMessage();
	}

	/**
	 * 转换为json字符串
	 * @param catalogList 分类列表
	 * @param testCaseList 测试用例列表
	 * @param productID 产品ID
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private String toJsonStr(List catalogList, List testCaseList, String productID) {
		JSONArray jsonArray = new JSONArray();

		for (Catalog catalog : (List<Catalog>) catalogList) {
			JSONObject attrObj = new JSONObject();
			attrObj.put("id", catalog.getId());
			attrObj.put("rel", "folder");

			JSONObject jsonResult = new JSONObject();
			jsonResult.put("attr", attrObj);
			jsonResult.put("data", catalog.getName()+" "); // 目前暂时添加" "，因为net.sf.json不支持如下字符 "[004]xxx[xx]他会认为最后一个[]内是一个json对象造成解析错误"
			if (catalogService.countCatalog(productID, catalog.getId())!=0 || testCaseService.countTestCase(productID, catalog.getId())!=0) {
				jsonResult.put("state", "closed");
			} else {
				jsonResult.put("state", "");
			}
			jsonArray.add(jsonResult);
		}

		for (TestCase testCase : (List<TestCase>) testCaseList) {
			JSONObject attrObj = new JSONObject();
			attrObj.put("id", testCase.getId());
			attrObj.put("rel", "default");

			JSONObject jsonResult = new JSONObject();
			jsonResult.put("attr", attrObj);
			jsonResult.put("data", testCase.getDescribing()+" "); // 目前暂时添加" "，因为net.sf.json不支持如下字符 "[004]xxx[xx]他会认为最后一个[]内是一个json对象造成解析错误"
			jsonResult.put("state", "");
			jsonArray.add(jsonResult);
		}

		return jsonArray.toString();
	}

	/**
	 * 转换为json字符串
	 * @param map 需要转换的map对象
	 * @return
	 */
	private String toJsonStr(Map<String, Object> map) {
		JSONObject attrObj = new JSONObject();
		for(Object obj : map.keySet()) {
			attrObj.put(obj, map.get(obj));
		}
		return attrObj.toString();
	}

}
